<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="author" content="doyouho, Gitee为https://gitee.com/kathy_candy" />
    <title>意休前端 | 实例集合</title>
    <link rel="shortcut icon" href="./static/baobao.png" type="image/png" />
    <link rel="bookmark" href="./static/baobao.png" />
    <link rel="stylesheet" href="./main.css" />
  </head>
  <body>
    <header class="header"><h1 class="iconLink"><a href="https://gitee.com/kathy_candy" target="_blank" title="跳转到作者Gitee主页">实例集</a></h1></header>
    <div class="dateTxt" data-week="THUR."><b>2022</b><b>11</b><b class="day">10</b></div>
    <div class="back"></div>
    <div class="topTxt"><span class="text1">JUST</span><a class="text2" href="https://kathy_candy.gitee.io/doit/" target="_blank" title="跳转到doit工具页面" data-text="&nbsp;&nbsp;&nbsp;do&nbsp;it&nbsp;!&nbsp;">&nbsp;&nbsp;&nbsp;do&nbsp;it&nbsp;!&nbsp;</a></div>
    <div class="content-wrapper">
      <a class="btn-main blogBtn" href="https://kathy_candy.gitee.io/blog/" target="_blank" title="正在建设中……">博客</a>
      <a class="btn-main yixiuBtn" href="https://kathy_candy.gitee.io/doyouho.io/" target="_blank" title="需要改……">意休</a>
      <div class="box">
        <div class="box-content">
          <canvas class="canvas" width="300" height="300"></canvas>
          <img class="avatar active" src="static/logo.jpg" alt="头像" title="点击切换到时钟并计时"/>
          <div class="box-title">
            <h2 class="title">花里胡哨的CSS</h2>
            <p> 毛玻璃效果，元素剪裁形状，文字发光、文字镂空&变色、彩色文本/黑白切文本</p>
            <p>【记忆】：filter特效类 clip裁剪类</p>
          </div>
          <div class="line">
            <div class="nextbtn">next</div>
          </div>
          <div class="boxmore">
            <section class="section active">
              <p>① <b>backdrop-filter: blur(30px)</b> 毛玻璃效果，该层不能有背景，由它模糊透明地映出底层。</p>
              <p>② <b>clip-path:circle(); shape-outside:circle();</b>元素、形状都用圆形路径裁出，图片用float使文字环绕，用margin添加间距(Not padding) 【裁剪后边框和阴影都不好使了】</p>
              <p>③ [详] <b>clip-path: polygon();</b> 多边形裁剪：用百分数写定位点，点之间用逗号，xy之间用空格，按点顺序绘制图形。（更多使用可看<a href="https://blog.csdn.net/weixin_44116302/article/details/98882841" title="clip-path路径裁剪">clip-path</a>）</p>
              <p>④ 文字发光：<b>text-shadow</b>叠加多层-同颜色+羽化渐增。</p>
              <p>⑤ 文字镂空&文字变色：把元素的文本(空格用&<span>nbsp;</span>)通过自定义属性传给父级的伪类元素(width:0%; height overflow)，该元素和其伪类元素都需要设置<b>-webkit-text-stroke</b>(不同的是该元素的color为transparent)，最后:hover激活时伪类元素(width:100%; <b>filter:drop-shadow(0 0 25px green);</b>)</p>
              <p>⑥ 彩色文本：给文本所在元素加渐变背景<b>background-image: linear-gradient(向哪渐变：0°为向上-可写成变量var(--rAngle),颜色1,颜色2...)</b>有颜色后跟空格和百分比位置的写法，用文本裁剪背景<b>-webkit-background-clip: text;</b>，文本填充颜色设成透明<b>-webkit-text-fill-color: transparent;</b>。（更多花样看<a href="https://blog.csdn.net/hncu1990/article/details/118878493" target="_blank" title="linear-gradient 和 radial-gradient">渐变文</a>）</p>
              <p>⑦ 同理可做成黑白切文本，将文本元素的背景A裁入文字，另增添一个和背景A渐变方向相反的背景B，把它放在文本层底层。</p>
            </section>
            <section class="section">
              <p>文字描边-绘制过程，边框变换，文字沿路径，曲线绘制，感应鼠标</p>
              <p>伪类元素默认是行级元素inline，设了position之后，加与不加display有什么区别</p>
              <p> transition: --rotate 9999s linear</p>
            </section>
            
          </div>
          
        </div>
        <div class="box-record">点击头像开始记录时间</div>
      </div>
      <div class="instance">
        <div class="instance-title">提高生活品质 JavaScript</div>
        <div class="instance-content">
          <ul class="instanceUl">
            <li>案例1：<a href="timeLine/timeline.html"  target="_blank">时间轴</a> <span>2023-01-29</span></li>
          </ul>
        </div>
        
      </div>
      
    </div>
    
    
    <script>
      const canvas = document.querySelector('.canvas');
      const ctx = canvas.getContext('2d');
      ctx.lineJoin = 'round'; // 连接处圆滑
      ctx.lineCap = 'round';  // 线段端点圆滑
      const cWidth = canvas.width, cHeight = canvas.height;
      let animationClock = null; // 用来获取requestAnimationFrame()对象，后期关闭cancelAnimationFrame()
      let weeklist = ['SUN.', 'MON.', 'TUE.', 'WED.', 'THUR.', 'FRI.', 'SAT.'];
      
      const odateTxt = document.querySelector('.dateTxt');
      const odateTxtBs = odateTxt.querySelectorAll('b');
      const onextbtn = document.querySelector('.nextbtn');
      const orecord = document.querySelector('.box-record');
      const photo = document.querySelector('.avatar');
      photo.onclick = switchFun;
      canvas.onclick = switchFun;
      renderClock('begin');
      function switchFun(){
        if(photo.classList.contains('active')){
          photo.classList.remove('active')
          canvas.classList.add('active');
          renderClock('begin'); // 默认执行时钟函数
          orecord.innerText = '正在计时……';
          
        }else{
          let countNum = +new Date() - orecord.getAttribute('data-begin');
          orecord.innerHTML = '本次记录为<span class="time">' + Math.round(countNum / 6000) / 10 + '</span>分钟';
          cancelAnimationFrame(animationClock);
          animationClock = null;
          canvas.classList.remove('active')
          photo.classList.add('active');
        }
      }
      
      onextbtn.onclick = function(){
        const osections = document.querySelectorAll('.section');
        let len = osections.length - 1;
        let index = orecord.getAttribute('data-index') * 1;
        let newone = index < len ? index + 1 : 0;
        osections[index].classList.remove('active');
        osections[newone].classList.add('active');
        orecord.setAttribute('data-index', newone);
      }
      
      function renderClock(type){
        const bg1 = '#242f37', bg2 = '#281e33', sign1='#bbb', sign2 = '#474561', hColor='#88ff66', sColor = '#ff6363', mColor = '#66f', pointColor = '#ff6363';
        const x = cWidth / 2, y= cHeight / 2, r = Math.min(x, y) * 0.98;
        const middleLine = cWidth / 100, size = '20px sans-serif', numLen = r-32;
        
        // 清空上次渲染
        ctx.clearRect(0, 0, cWidth, cHeight);
        
        // 绘制钟表背景
        const color = ctx.createLinearGradient(0, 0, cWidth, 0);
        color.addColorStop(0, bg1);
        color.addColorStop(1, bg2);
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(x, y, r, 0, 2 * Math.PI, true);
        ctx.fill();
        // ctx.shadowOffsetX = 6;
        // ctx.shadowOffsetY = 6;
        // ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
        // ctx.shadowBlur = 20; //模糊半径
        ctx.closePath();
        
        
        // 先存档save，确定坐标原点translate，0°位置rotate。
        ctx.save(); // A层
        // 绘制指针 和 表盘数字
        ctx.translate(x, y); // 坐标原点居中
        ctx.rotate(-Math.PI / 2); // x轴逆时针旋转
        ctx.save(); // B层
        
        ctx.strokeStyle = sign1;
        ctx.lineWidth = middleLine;
        for(let i = 0; i < 12; i++){
          ctx.beginPath();
          ctx.moveTo(r - 14, 0);
          ctx.lineTo(r - 6, 0);
          ctx.stroke();
          ctx.closePath();
          ctx.rotate(2 * Math.PI / 12);
        }
        ctx.restore(); // B层
        ctx.save(); 
        
        ctx.strokeStyle = sign2;
        ctx.lineWidth = 2;
        for(let i = 0; i < 60; i++){
          if(i % 5 !== 0){
            ctx.beginPath();
            ctx.moveTo(r - 10, 0);
            ctx.lineTo(r - 6, 0);
            ctx.stroke();
            ctx.closePath();
          }
          ctx.rotate(2 * Math.PI / 60);
        }
        ctx.restore(); // B层
        ctx.save(); 
        
        // 数字
        ctx.font = size;
        ctx.fillStyle = sign1;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.rotate(Math.PI / 2);  // 坐标轴x必须旋转回3点处，这样的文本才会方向正确
        for(let i = 1; i <= 12; i++){
          let angle = (i - 3) * (Math.PI * 2) / 12;
          let numX = numLen * Math.cos(angle);
          let numY = numLen * Math.sin(angle);
          ctx.fillText(i, numX, numY); // 文本,中线位置x,y
        }
        ctx.rotate(- Math.PI / 2); // 坐标轴x恢复到12点处
        ctx.restore(); // B层
        ctx.save(); 
        
        // 当前time
        var time = new Date();
        var h = 2 * Math.PI / 12 * (time.getHours() % 12);
        var m = 2 * Math.PI / 60 * time.getMinutes();
        var s = 2 * Math.PI / 60 * time.getSeconds();
        if(type === 'begin'){
          orecord.setAttribute('data-begin', +time);
          odateTxt.setAttribute('data-week', weeklist[time.getDay()]);
          odateTxtBs[0].innerText = time.getFullYear();
          odateTxtBs[1].innerText = time.getMonth() + 1;
          odateTxtBs[2].innerText = time.getDate();
        }
        // 绘制秒针
        ctx.rotate(s);
        ctx.beginPath();
        ctx.moveTo(-6, 0);
        ctx.lineTo(r - r / 7, 0);
        ctx.strokeStyle = sColor;
        ctx.lineWidth = 2;
        ctx.stroke();
        ctx.closePath();
        ctx.restore(); // B层
        ctx.save();
        
        // 绘制分针
        ctx.rotate(m + s / 60);
        ctx.beginPath();
        ctx.moveTo(-6, -2.6);
        ctx.lineTo(-6, 2.6);
        ctx.lineTo(r * 0.6, 2);
        ctx.lineTo(r * 0.68, 1);
        ctx.lineTo(r * 0.68, -1);
        ctx.lineTo(r * 0.6, -2);
        ctx.fillStyle = mColor;
        ctx.fill();
        
        // ctx.moveTo(-6, 0);
        // ctx.lineTo(r * 0.8, 0);
        // ctx.strokeStyle = mColor;
        // ctx.lineWidth = 4;
        // ctx.stroke();
        
        ctx.closePath();
        ctx.restore(); // B层
        ctx.save();
        
        // 绘制时针
        ctx.rotate(h + m / 12 + s / 12 / 60);
        ctx.beginPath();
        ctx.moveTo(-6, -3);
        ctx.lineTo(-6, 3);
        ctx.lineTo(r * 0.43, 2.4);
        ctx.lineTo(r * 0.5, 1);
        ctx.lineTo(r * 0.5, -1);
        ctx.lineTo(r * 0.43, -2.4);
        ctx.fillStyle = hColor;
        ctx.fill();
        // ctx.moveTo(-6, 0);
        // ctx.lineTo(r * 0.6, 0);
        // ctx.strokeStyle = sign1;
        // ctx.lineWidth = middleLine > 4 ? middleLine : 4;
        // ctx.stroke();
        ctx.closePath();
        ctx.restore(); // B层
        
        
        
        
        ctx.beginPath();
        ctx.arc(0, 0, middleLine+2, 0, 2*Math.PI,true);
        ctx.fillStyle = hColor;
        ctx.fill();
        ctx.closePath();
        
        ctx.restore(); // A层 恢复到最外层操作--为了每秒重新绘制，确保坐标原点
        
        animationClock = requestAnimationFrame(renderClock);
      }
        
    </script>
  </body>
</html>